//////////////////////////////////////////////////////////////////////
////                                                              ////
////  CFDatabusDecoder.v                                          ////
////                                                              ////
////                                                              ////
////  This file is part of the "Pico E12" project                 ////
////  http://www.picocomputing.com                                ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2005, Picocomputing, Inc.                      ////
//// http://www.picocomputing.com/                                ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////////////////////////////////////////////////////////////////////JF

//This module handles the decoding and latching of the internal databus

`include "PicoDefines.v"

`timescale 10ns / 1ns
module CFDatabusDecoder(CE1, CE2, A0, DIN, DOUT, ReadLatch, WriteLatch, DataIn, DataOut);

input CE1;                                                             //Card Enable 1
input CE2;                                                             //Card Enable 2
input A0;                                                              //Address Line 0 
input [15:0]DIN;                                                       //Raw Databus In [Host -> Pico]
output [15:0]DOUT;                                                     //Raw Databus Out [Pico -> Host]
input ReadLatch;                                                       //Read Latch In
input WriteLatch;                                                      //Write Latch In
output [15:0]DataIn;                                                   //Data in to peripherals [Host -> Pico]
input [15:0]DataOut;                                                   //Data out ot peripherals [Pico -> Host]
																							  
wire CE1;
wire CE2;
wire A0;
wire [15:0]DIN;
reg [15:0]DOUT;
wire ReadLatch;
wire WriteLatch;
reg [15:0]DataIn;
wire [15:0]DataOut;

wire [15:0]DataInMuxed;                                                //Byte steering mux for data from peripherals
wire [7:0]DataOutMuxed;                                                //Byte steering mux for data from peripherals
wire ReadSwapLSBs;                                                     //Byte steering signals
wire WriteSwapMSBs;                                                    
wire WriteSwapLSBs;                                                    

reg WriteSwapLSBsLatch;                                               
reg WriteSwapMSBsLatch;                                                //Latched byte steering signals
reg ReadSwapLSBsLatch;                                                 


wire CE1SwapReset;                                                     //Reset signals for the byte steering latches
wire CE2SwapReset;                                                     

assign ReadSwapLSBs = (ReadLatch) && (CE2) && (~CE1) && (A0);          //This code detects 8 bit reads and writes and performs byte steering if necessary
assign WriteSwapLSBs = (WriteLatch) && (~CE2) && (CE1);
assign WriteSwapMSBs = (WriteLatch) && (CE2) && (~CE1);

assign CE2SwapReset = ((~CE1) && (~CE2)) || (~CE2);                    //Byte steering latch reset signals
assign CE1SwapReset = ((~CE1) && (~CE2)) || (~CE1);

always @(ReadSwapLSBs or CE2SwapReset or ReadSwapLSBsLatch) begin      //Databus latches 
	if (CE2SwapReset) ReadSwapLSBsLatch <= 0;
else
	if (ReadSwapLSBs) ReadSwapLSBsLatch <= 1;
end

always @(WriteSwapLSBs or CE1SwapReset or WriteSwapLSBsLatch) begin
	if (CE1SwapReset) WriteSwapLSBsLatch <= 0;
else
	if (WriteSwapLSBs) WriteSwapLSBsLatch <= 1;
end

always @(WriteSwapMSBs or CE2SwapReset or WriteSwapMSBsLatch) begin
	if (CE2SwapReset) WriteSwapMSBsLatch <= 0;
else
	if (WriteSwapMSBs) WriteSwapMSBsLatch <= 1;
end

assign DataInMuxed[15:8] = (WriteSwapMSBsLatch)?DIN[7:0] : DIN[15:8];
assign DataInMuxed[7:0] = (WriteSwapLSBsLatch)?DIN[15:8] : DIN[7:0]; 

assign DataOutMuxed[7:0] = (ReadSwapLSBsLatch)?DataOut[15:8] : DataOut[7:0];


//------------------------Databus Latches-----------------------------//
always @(WriteLatch or DataIn or DataInMuxed)
	if (WriteLatch) DataIn[15:0] <= DataInMuxed[15:0];

always @(DOUT[15:0] or DataOut[15:0] or DataOutMuxed[7:0] or ReadLatch)
begin														 
	if (ReadLatch) begin
		DOUT[15:8] <= DataOut[15:8];
		DOUT[7:0] <= DataOutMuxed[7:0];
	end
end

endmodule